Sensor Fusion for Kinetis MCUs (ISSDK/KSDK version)
control.h File Reference
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ControlSubsystem
 

Typedefs

typedef struct ControlSubsystem ControlSubsystem
 
Control Port Function Type Definitions

The "write" and "stream" commands provide two control functions visible at the main() level. These typedefs define the structure of those two calls.

typedef int8_t( writePort_t) (struct ControlSubsystem *pComm, uint8_t buffer[], uint16_t nbytes)
 
typedef void( streamData_t) (SensorFusionGlobals *sfg, uint8_t *sUARTOutputBuffer)
 

Functions

int8_t initializeControlPort (ControlSubsystem *pComm)
 
void CreateAndSendPackets (SensorFusionGlobals *sfg, uint8_t *sUARTOutputBuffer)
 
void DecodeCommandBytes (SensorFusionGlobals *sfg, char iCommandBuffer[], uint8 sUART_InputBuffer[], uint16 nbytes)
 
void BlueRadios_Init (void)
 
void sBufAppendItem (uint8_t *pDest, uint16_t *pIndex, uint8_t *pSource, uint16_t iBytesToCopy)
 

Variables

uint8_t sUARTOutputBuffer [256]
 

Detailed Description

Each sensor fusion application will probably have its own set of functions to control the fusion process and report results. This file defines the programming interface that should be followed in order for the fusion functions to operate correctly out of the box. The actual command interpreter is defined separately in DecodeCommandBytes.c. The output streaming function is defined in output_stream.c. Via these three files, the NXP Sensor Fusion Library provides a default set of functions which are compatible with the Sensor Fusion Toolbox. Use of the toolbox is highly recommended at least during initial development, as it provides many useful debug features. The NXP development team will typically require use of the toolbox as a pre-requisite for providing software support.

Definition in file control.h.

Typedef Documentation

he ControlSubsystem encapsulates command and data streaming functions.

The ControlSubsystem encapsulates command and data streaming functions for the library. A C++-like typedef structure which includes executable methods for the subsystem is defined here.

typedef void( streamData_t) (SensorFusionGlobals *sfg, uint8_t *sUARTOutputBuffer)

Definition at line 56 of file control.h.

typedef int8_t( writePort_t) (struct ControlSubsystem *pComm, uint8_t buffer[], uint16_t nbytes)

Definition at line 55 of file control.h.

Function Documentation

void BlueRadios_Init ( void  )

Used to initialize the Blue Radios Bluetooth module found on the FRDM-FXS-MULT2-B sensor shield from NXP.

Definition at line 132 of file control.c.

Referenced by initializeControlPort().

133 {
134  uint16_t ilen; // command string length
135 
136  // transmit "ATSRM,2,0\r" to minimize traffic from the module
137  // command "ATSRM": sets the module response mode which configures how verbose the module will be
138  // 2: response mode at to minimal
139  // 0: disconnected mode is command mode
140  // \r: carriage return escape sequence
141  strcpy((char *)sUARTOutputBuffer, "ATSRM,2,0\r");
142  ilen = strlen((char *)sUARTOutputBuffer);
144  return;
145 }
int8_t writeWirelessPort(uint8_t buffer[], uint16_t nbytes)
Definition: control.c:99
uint8_t sUARTOutputBuffer[256]
main output buffer defined in control.c
Definition: control.c:59

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void CreateAndSendPackets ( SensorFusionGlobals sfg,
uint8_t *  sUARTOutputBuffer 
)

Called once per fusion cycle to stream information required by the NXP Sensor Fusion Toolbox. Packet protocols are defined in the NXP Sensor Fusion for Kinetis Product Development Kit User Guide.

Definition at line 144 of file output_stream.c.

Referenced by initializeControlPort().

145 {
146  Quaternion fq; // quaternion to be transmitted
147  float ftmp; // scratch
148  static uint32_t iTimeStamp = 0; // 1MHz time stamp
149  uint16_t iIndex; // output buffer counter
150  int32_t scratch32; // scratch int32_t
151  int16_t scratch16; // scratch int16_t
152  int16_t iPhi,
153  iThe,
154  iRho; // integer angles to be transmitted
155  int16_t iDelta; // magnetic inclination angle if available
156  int16_t iOmega[3]; // scaled angular velocity vector
157  uint16_t isystick; // algorithm systick time
158  int16_t i, j, k; // general purpose
159  uint8_t tmpuint8_t; // scratch uint8_t
160  uint8_t flags; // byte of flags
161  uint8_t AngularVelocityPacketOn,
162  DebugPacketOn,
163  RPCPacketOn;
164  int8_t AccelCalPacketOn;
165  static uint8_t iPacketNumber = 0; // packet number
166 
167  // update the 1MHz time stamp counter expected by the PC GUI (independent of project clock rates)
168  iTimeStamp += 1000000 / FUSION_HZ;
169 
170 #if (MAXPACKETRATEHZ < FUSION_HZ)
171  uint8_t skip_packet = throttle(); // possible UART bandwidth problem
172  if (skip_packet) return; // need to skip packet transmission to avoid UART overrun
173 #endif
174 
175  // cache local copies of control flags so we don't have to keep dereferencing pointers below
176  quaternion_type quaternionPacketType;
177  quaternionPacketType = sfg->pControlSubsystem->QuaternionPacketType;
178  AngularVelocityPacketOn = sfg->pControlSubsystem->AngularVelocityPacketOn;
179  DebugPacketOn = sfg->pControlSubsystem->DebugPacketOn;
180  RPCPacketOn = sfg->pControlSubsystem->RPCPacketOn;
181  AccelCalPacketOn = sfg->pControlSubsystem->AccelCalPacketOn;
182 
183  // zero the counter for bytes accumulated into the transmit buffer
184  iIndex = 0;
185 
186  // ************************************************************************
187  // Main type 1: range 0 to 35 = 36 bytes
188  // Debug type 2: range 0 to 7 = 8 bytes
189  // Angular velocity type 3: range 0 to 13 = 14 bytes
190  // Euler angles type 4: range 0 to 13 = 14 bytes
191  // Altitude/Temp type 5: range 0 to 13 = 14 bytes
192  // Magnetic type 6: range 0 to 16 = 18 bytes
193  // Kalman packet 7: range 0 to 47 = 48 bytes
194  // Precision Accelerometer packet 8: range 0 to 46 = 47 bytes
195  //
196  // Total excluding intermittent packet 8 is:
197  // 152 bytes vs 256 bytes size of sUARTOutputBuffer
198  // at 25Hz, data rate is 25*152 = 3800 bytes/sec = 38.0kbaud = 33% of 115.2kbaud
199  // at 40Hz, data rate is 40*152 = 6080 bytes/sec = 60.8kbaud = 53% of 115.2kbaud
200  // at 50Hz, data rate is 50*152 = 7600 bytes/sec = 76.0kbaud = 66% of 115.2kbaud
201  // ************************************************************************
202  // ************************************************************************
203  // fixed length packet type 1
204  // this packet type is always transmitted
205  // total size is 0 to 35 equals 36 bytes
206  // ************************************************************************
207  // [0]: packet start byte (need a iIndex++ here since not using sBufAppendItem)
208  sUARTOutputBuffer[iIndex++] = 0x7E;
209 
210  // [1]: packet type 1 byte (iIndex is automatically updated in sBufAppendItem)
211  tmpuint8_t = 0x01;
212  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
213 
214  // [2]: packet number byte
215  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
216  iPacketNumber++;
217 
218  // [6-3]: 1MHz time stamp (4 bytes)
219  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iTimeStamp, 4);
220 
221  // [12-7]: integer accelerometer data words (scaled to 8192 counts per g for PC GUI)
222  // send non-zero data only if the accelerometer sensor is enabled and used by the selected quaternion
223  if (sfg->iFlags & F_USING_ACCEL) {
224  switch (quaternionPacketType)
225  {
226  case Q3:
227  case Q6MA:
228  case Q6AG:
229  case Q9:
230 #if F_USING_ACCEL
231  // accelerometer data is used for the selected quaternion so transmit but clip at 4g
232  scratch32 = (sfg->Accel.iGc[CHX] * 8192) / sfg->Accel.iCountsPerg;
233  if (scratch32 > 32767) scratch32 = 32767;
234  if (scratch32 < -32768) scratch32 = -32768;
235  scratch16 = (int16_t) (scratch32);
236  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
237 
238  scratch32 = (sfg->Accel.iGc[CHY] * 8192) / sfg->Accel.iCountsPerg;
239  if (scratch32 > 32767) scratch32 = 32767;
240  if (scratch32 < -32768) scratch32 = -32768;
241  scratch16 = (int16_t) (scratch32);
242  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
243 
244  scratch32 = (sfg->Accel.iGc[CHZ] * 8192) / sfg->Accel.iCountsPerg;
245  if (scratch32 > 32767) scratch32 = 32767;
246  if (scratch32 < -32768) scratch32 = -32768;
247  scratch16 = (int16_t) (scratch32);
248  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
249  break;
250 #endif // F_USING_ACCEL
251  case Q3M:
252  case Q3G:
253  default:
254  // accelerometer data is not used in currently selected algorithm so transmit zero
255  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
256  break;
257  }
258  } else {
259  // accelerometer structure is not defined so transmit zero
260  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
261  }
262  // [18-13]: integer calibrated magnetometer data words (already scaled to 10 count per uT for PC GUI)
263  // send non-zero data only if the magnetometer sensor is enabled and used by the selected quaternion
264  if (sfg->iFlags & F_USING_MAG)
265  switch (quaternionPacketType)
266  {
267  case Q3M:
268  case Q6MA:
269  case Q9:
270 #if F_USING_MAG
271  // magnetometer data is used for the selected quaternion so transmit
272  scratch16 = (int16_t) (sfg->Mag.iBc[CHX] * 10) / (sfg->Mag.iCountsPeruT);
273  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
274  scratch16 = (int16_t) ((sfg->Mag.iBc[CHY] * 10) / sfg->Mag.iCountsPeruT);
275  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
276  scratch16 = (int16_t) ((sfg->Mag.iBc[CHZ] * 10) / sfg->Mag.iCountsPeruT);
277  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
278  break;
279 #endif
280  // magnetometer data is not used in currently selected algorithm so transmit zero
281  case Q3:
282  case Q3G:
283  case Q6AG:
284  default:
285  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
286  break;
287  }
288  else
289  {
290  // magnetometer structure is not defined so transmit zero
291  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
292  }
293 
294  // [24-19]: uncalibrated gyro data words (scaled to 20 counts per deg/s for PC GUI)
295  // send non-zero data only if the gyro sensor is enabled and used by the selected quaternion
296  if (sfg->iFlags & F_USING_GYRO)
297  {
298  switch (quaternionPacketType)
299  {
300  case Q3G:
301  case Q6AG:
302 #if F_USING_GYRO
303  case Q9:
304 
305  // gyro data is used for the selected quaternion so transmit
306  scratch16 = (int16_t) ((sfg->Gyro.iYs[CHX] * 20) / sfg->Gyro.iCountsPerDegPerSec);
307  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
308  scratch16 = (int16_t) ((sfg->Gyro.iYs[CHY] * 20) / sfg->Gyro.iCountsPerDegPerSec);
309  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
310  scratch16 = (int16_t) ((sfg->Gyro.iYs[CHZ] * 20) / sfg->Gyro.iCountsPerDegPerSec);
311  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
312  break;
313 #endif
314  case Q3:
315  case Q3M:
316  case Q6MA:
317  default:
318  // gyro data is not used in currently selected algorithm so transmit zero
319  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
320  break;
321  }
322  }
323  else
324  {
325  // gyro structure is not defined so transmit zero
326  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
327  }
328 
329  // initialize default quaternion, flags byte, angular velocity and orientation
330  fq.q0 = 1.0F;
331  fq.q1 = fq.q2 = fq.q3 = 0.0F;
332  flags = 0x00;
333  iOmega[CHX] = iOmega[CHY] = iOmega[CHZ] = 0;
334  iPhi = iThe = iRho = iDelta = 0;
335  isystick = 0;
336 
337  // flags byte 33: quaternion type in least significant nibble
338  // Q3: coordinate nibble, 1
339  // Q3M: coordinate nibble, 6
340  // Q3G: coordinate nibble, 3
341  // Q6MA: coordinate nibble, 2
342  // Q6AG: coordinate nibble, 4
343  // Q9: coordinate nibble, 8
344  // flags byte 33: coordinate in most significant nibble
345  // Aerospace/NED: 0, quaternion nibble
346  // Android: 1, quaternion nibble
347  // Windows 8: 2, quaternion nibble
348  // set the quaternion, flags, angular velocity and Euler angles
349  switch (quaternionPacketType)
350  {
351 #if F_3DOF_G_BASIC
352  case Q3:
353  if (sfg->iFlags & F_3DOF_G_BASIC)
354  {
355  flags |= 0x01;
356  readCommon((SV_ptr)&sfg->SV_3DOF_G_BASIC, &fq, &iPhi, &iThe, &iRho, iOmega, &isystick);
357  }
358  break;
359 #endif
360 #if F_3DOF_B_BASIC
361  case Q3M:
362  if (sfg->iFlags & F_3DOF_B_BASIC)
363  {
364  flags |= 0x06;
365  readCommon((SV_ptr)&sfg->SV_3DOF_B_BASIC, &fq, &iPhi, &iThe, &iRho, iOmega, &isystick);
366  }
367  break;
368 #endif
369 #if F_3DOF_Y_BASIC
370  case Q3G:
371  if (sfg->iFlags & F_3DOF_Y_BASIC)
372  {
373  flags |= 0x03;
374  readCommon((SV_ptr)&sfg->SV_3DOF_Y_BASIC, &fq, &iPhi, &iThe, &iRho, iOmega, &isystick);
375  }
376  break;
377 #endif
378 #if F_6DOF_GB_BASIC
379  case Q6MA:
380  if (sfg->iFlags & F_6DOF_GB_BASIC)
381  {
382  flags |= 0x02;
383  iDelta = (int16_t) (10.0F * sfg->SV_6DOF_GB_BASIC.fLPDelta);
384  readCommon((SV_ptr)&sfg->SV_6DOF_GB_BASIC, &fq, &iPhi, &iThe, &iRho, iOmega, &isystick);
385  }
386  break;
387 #endif
388 #if F_6DOF_GY_KALMAN
389  case Q6AG:
390  if (sfg->iFlags & F_6DOF_GY_KALMAN)
391  {
392  flags |= 0x04;
393  readCommon((SV_ptr)&sfg->SV_6DOF_GY_KALMAN, &fq, &iPhi, &iThe, &iRho, iOmega, &isystick);
394  }
395  break;
396 #endif
397 #if F_9DOF_GBY_KALMAN
398  case Q9:
399  if (sfg->iFlags & F_9DOF_GBY_KALMAN)
400  {
401  flags |= 0x08;
402  iDelta = (int16_t) (10.0F * sfg->SV_9DOF_GBY_KALMAN.fDeltaPl);
403  readCommon((SV_ptr)&sfg->SV_9DOF_GBY_KALMAN, &fq, &iPhi, &iThe, &iRho, iOmega, &isystick);
404  }
405  break;
406 #endif
407  default:
408  // use the default data already initialized
409  break;
410  }
411 
412  // [32-25]: scale the quaternion (30K = 1.0F) and add to the buffer
413  scratch16 = (int16_t) (fq.q0 * 30000.0F);
414  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
415  scratch16 = (int16_t) (fq.q1 * 30000.0F);
416  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
417  scratch16 = (int16_t) (fq.q2 * 30000.0F);
418  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
419  scratch16 = (int16_t) (fq.q3 * 30000.0F);
420  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
421 
422  // set the coordinate system bits in flags from default NED (00)
423 #if THISCOORDSYSTEM == ANDROID
424  // set the Android flag bits
425  flags |= 0x10;
426 #elif THISCOORDSYSTEM == WIN8
427  // set the Win8 flag bits
428  flags |= 0x20;
429 #endif // THISCOORDSYSTEM
430 
431  // [33]: add the flags byte to the buffer
432  sBufAppendItem(sUARTOutputBuffer, &iIndex, &flags, 1);
433 
434  // [34]: add the shield (bits 7-5) and Kinetis (bits 4-0) byte
435  tmpuint8_t = ((THIS_SHIELD & 0x07) << 5) | (THIS_BOARD & 0x1F);
436  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
437 
438  // [35]: add the tail byte for the standard packet type 1
439  sUARTOutputBuffer[iIndex++] = 0x7E;
440 
441  // ************************************************************************
442  // Variable length debug packet type 2
443  // total size is 0 to 7 equals 8 bytes
444  // ************************************************************************
445  if (DebugPacketOn)
446  {
447  // [0]: packet start byte
448  sUARTOutputBuffer[iIndex++] = 0x7E;
449 
450  // [1]: packet type 2 byte
451  tmpuint8_t = 0x02;
452  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
453 
454  // [2]: packet number byte
455  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
456  iPacketNumber++;
457 
458  // [4-3] software version number
459  scratch16 = THISBUILD;
460  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
461 
462  // [6-5] systick count / 20
463  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &isystick, 2);
464 
465  // [7 in practice but can be variable]: add the tail byte for the debug packet type 2
466  sUARTOutputBuffer[iIndex++] = 0x7E;
467  }
468 
469  // ************************************************************************
470  // Angular Velocity packet type 3
471  // total bytes for packet type 2 is range 0 to 13 = 14 bytes
472  // ************************************************************************
473  if (AngularVelocityPacketOn)
474  {
475  // [0]: packet start byte
476  sUARTOutputBuffer[iIndex++] = 0x7E;
477 
478  // [1]: packet type 3 byte (angular velocity)
479  tmpuint8_t = 0x03;
480  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
481 
482  // [2]: packet number byte
483  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
484  iPacketNumber++;
485 
486  // [6-3]: time stamp (4 bytes)
487  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iTimeStamp, 4);
488 
489  // [12-7]: add the scaled angular velocity vector to the output buffer
490  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iOmega[CHX], 2);
491  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iOmega[CHY], 2);
492  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iOmega[CHZ], 2);
493 
494  // [13]: add the tail byte for the angular velocity packet type 3
495  sUARTOutputBuffer[iIndex++] = 0x7E;
496  }
497 
498  // ************************************************************************
499  // Roll, Pitch, Compass Euler angles packet type 4
500  // total bytes for packet type 4 is range 0 to 13 = 14 bytes
501  // ************************************************************************
502  if (RPCPacketOn)
503  {
504  // [0]: packet start byte
505  sUARTOutputBuffer[iIndex++] = 0x7E;
506 
507  // [1]: packet type 4 byte (Euler angles)
508  tmpuint8_t = 0x04;
509  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
510 
511  // [2]: packet number byte
512  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
513  iPacketNumber++;
514 
515  // [6-3]: time stamp (4 bytes)
516  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iTimeStamp, 4);
517 
518  // [12-7]: add the angles (resolution 0.1 deg per count) to the transmit buffer
519  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iPhi, 2);
520  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iThe, 2);
521  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iRho, 2);
522 
523  // [13]: add the tail byte for the roll, pitch, compass angle packet type 4
524  sUARTOutputBuffer[iIndex++] = 0x7E;
525  }
526 
527  // ************************************************************************
528  // Altitude / Temperature packet type 5
529  // total bytes for packet type 5 is range 0 to 13 = 14 bytes
530  // ************************************************************************
531 #if F_USING_PRESSURE
532  if (sfg->iFlags & F_1DOF_P_BASIC)
533  {
534  if (sfg->pControlSubsystem->AltPacketOn && sfg->Pressure.iWhoAmI)
535  {
536  // [0]: packet start byte
537  sUARTOutputBuffer[iIndex++] = 0x7E;
538 
539  // [1]: packet type 5 byte
540  tmpuint8_t = 0x05;
541  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
542 
543  // [2]: packet number byte
544  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
545  iPacketNumber++;
546 
547  // [6-3]: time stamp (4 bytes)
548  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &iTimeStamp,
549  4);
550 
551  // [10-7]: altitude (4 bytes, metres times 1000)
552  scratch32 = (int32_t) (sfg->SV_1DOF_P_BASIC.fLPH * 1000.0F);
553  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch32, 4);
554 
555  // [12-11]: temperature (2 bytes, deg C times 100)
556  scratch16 = (int16_t) (sfg->SV_1DOF_P_BASIC.fLPT * 100.0F);
557  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
558 
559  // [13]: add the tail byte for the altitude / temperature packet type 5
560  sUARTOutputBuffer[iIndex++] = 0x7E;
561  }
562  }
563 #endif
564 
565  // ************************************************************************
566  // magnetic buffer packet type 6
567  // currently total size is 0 to 17 equals 18 bytes
568  // this packet is only transmitted if a magnetic algorithm is computed
569  // ************************************************************************
570 #if F_USING_MAG
571  static int16_t MagneticPacketID = 0; // magnetic packet number
572  if (sfg->iFlags & F_USING_MAG)
573  {
574  // [0]: packet start byte
575  sUARTOutputBuffer[iIndex++] = 0x7E;
576 
577  // [1]: packet type 6 byte
578  tmpuint8_t = 0x06;
579  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
580 
581  // [2]: packet number byte
582  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
583  iPacketNumber++;
584 
585  // [4-3]: number of active measurements in the magnetic buffer
587  (uint8_t *) &(sfg->MagBuffer.iMagBufferCount), 2);
588 
589  // [6-5]: fit error (%) with resolution 0.01%
590  if (sfg->MagCal.fFitErrorpc > 327.67F)
591  scratch16 = 32767;
592  else
593  scratch16 = (int16_t) (sfg->MagCal.fFitErrorpc * 100.0F);
594  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
595 
596  // [8-7]: geomagnetic field strength with resolution 0.1uT
597  scratch16 = (int16_t) (sfg->MagCal.fB * 10.0F);
598  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
599 
600  // always calculate magnetic buffer row and column (low overhead and saves warnings)
601  k = MagneticPacketID - 10;
602  j = k / MAGBUFFSIZEX;
603  i = k - j * MAGBUFFSIZEX;
604 
605  // [10-9]: int16_t: ID of magnetic variable to be transmitted
606  // ID 0 to 4 inclusive are magnetic calibration coefficients
607  // ID 5 to 9 inclusive are for future expansion
608  // ID 10 to (MAGBUFFSIZEX=12) * (MAGBUFFSIZEY=24)-1 or 10 to 10+288-1 are magnetic buffer elements
609  // where the convention is used that a negative value indicates empty buffer element (index=-1)
610  if ((MagneticPacketID >= 10) && (sfg->MagBuffer.index[i][j] == -1))
611  {
612  // use negative ID to indicate inactive magnetic buffer element
613  scratch16 = -MagneticPacketID;
614  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
615  }
616  else
617  {
618  // use positive ID unchanged for variable or active magnetic buffer entry
619  scratch16 = MagneticPacketID;
620  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
621  }
622 
623  // [12-11]: int16_t: variable 1 to be transmitted this iteration
624  // [14-13]: int16_t: variable 2 to be transmitted this iteration
625  // [16-15]: int16_t: variable 3 to be transmitted this iteration
626  switch (MagneticPacketID)
627  {
628  case 0:
629  // item 1: currently unused
630  scratch16 = 0;
631  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
632 
633  // item 2: currently unused
634  scratch16 = 0;
635  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
636 
637  // item 3: magnetic inclination angle with resolution 0.1 deg
638  scratch16 = iDelta;
639  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
640  break;
641 
642  case 1:
643  // items 1 to 3: hard iron components range -3276uT to +3276uT encoded with 0.1uT resolution
644  scratch16 = (int16_t) (sfg->MagCal.fV[CHX] * 10.0F);
645  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
646  scratch16 = (int16_t) (sfg->MagCal.fV[CHY] * 10.0F);
647  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
648  scratch16 = (int16_t) (sfg->MagCal.fV[CHZ] * 10.0F);
649  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
650  break;
651 
652  case 2:
653  // items 1 to 3: diagonal soft iron range -32. to +32. encoded with 0.001 resolution
654  scratch16 = (int16_t) (sfg->MagCal.finvW[CHX][CHX] * 1000.0F);
655  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
656  scratch16 = (int16_t) (sfg->MagCal.finvW[CHY][CHY] * 1000.0F);
657  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
658  scratch16 = (int16_t) (sfg->MagCal.finvW[CHZ][CHZ] * 1000.0F);
659  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
660  break;
661 
662  case 3:
663  // items 1 to 3: off-diagonal soft iron range -32. to +32. encoded with 0.001 resolution
664  scratch16 = (int16_t) (sfg->MagCal.finvW[CHX][CHY] * 1000.0F);
665  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
666  scratch16 = (int16_t) (sfg->MagCal.finvW[CHX][CHZ] * 1000.0F);
667  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
668  scratch16 = (int16_t) (sfg->MagCal.finvW[CHY][CHZ] * 1000.0F);
669  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
670  break;
671 
672  case 4:
673  case 5:
674  case 6:
675  case 7:
676  case 8:
677  case 9:
678  // cases 4 to 9 inclusive are for future expansion so transmit zeroes for now
679  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
680  break;
681 
682  default:
683  // 10 and upwards: this handles the magnetic buffer elements
685  (uint8_t *) &(sfg->MagBuffer.iBs[CHX][i][j]), 2);
687  (uint8_t *) &(sfg->MagBuffer.iBs[CHY][i][j]), 2);
689  (uint8_t *) &(sfg->MagBuffer.iBs[CHZ][i][j]), 2);
690  break;
691  }
692 
693  // wrap the variable ID back to zero if necessary
694  MagneticPacketID++;
695  if (MagneticPacketID >= (10 + MAGBUFFSIZEX * MAGBUFFSIZEY))
696  MagneticPacketID = 0;
697 
698  // [17]: add the tail byte for the magnetic packet type 6
699  sUARTOutputBuffer[iIndex++] = 0x7E;
700  }
701 #endif
702 
703  // *******************************************************************************
704  // Kalman filter packet type 7
705  // total bytes for packet type 7 is range 0 to 41 inclusive = 42 bytes
706  // this packet is only transmitted when a Kalman algorithm is computed
707  // and then non-zero data is transmitted only when a Kalman quaternion is selected
708  // *******************************************************************************
709  bool kalman = false;
710 #if F_6DOF_GY_KALMAN
711  uint8_t six_axis_kalman = (sfg->iFlags & F_6DOF_GY_KALMAN) && (quaternionPacketType == Q6AG);
712  kalman = six_axis_kalman;
713 #endif
714 #if F_9DOF_GBY_KALMAN
715  uint8_t nine_axis_kalman = (sfg->iFlags & F_9DOF_GBY_KALMAN) && (quaternionPacketType == Q9);
716  kalman = kalman | nine_axis_kalman;
717 #endif
718 #if F_6DOF_GY_KALMAN || F_9DOF_GBY_KALMAN
719  if (kalman)
720  {
721  if ((quaternionPacketType == Q6AG) || (quaternionPacketType == Q9))
722  {
723  // [0]: packet start byte
724  sUARTOutputBuffer[iIndex++] = 0x7E;
725 
726  // [1]: packet type 7 byte
727  tmpuint8_t = 0x07;
728  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
729 
730  // [2]: packet number byte
731  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
732  iPacketNumber++;
733 
734  // [4-3]: fzgErr[CHX] resolution scaled by 30000
735  // [6-5]: fzgErr[CHY] resolution scaled by 30000
736  // [8-7]: fzgErr[CHZ] resolution scaled by 30000
737  for (i = CHX; i <= CHZ; i++)
738  {
739 #if F_6DOF_GY_KALMAN
740  if (six_axis_kalman) scratch16 = (int16_t) (sfg->SV_6DOF_GY_KALMAN.fZErr[i] * 30000.0F);
741 #endif
742 #if F_9DOF_GBY_KALMAN
743  if (nine_axis_kalman) scratch16 = (int16_t) (sfg->SV_9DOF_GBY_KALMAN.fZErr[i] * 30000.0F);
744 #endif
745  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16,2);
746  }
747 
748  // [10-9]: fgErrPl[CHX] resolution scaled by 30000
749  // [12-11]: fgErrPl[CHY] resolution scaled by 30000
750  // [14-13]: fgErrPl[CHZ] resolution scaled by 30000
751  for (i = CHX; i <= CHZ; i++)
752  {
753 #if F_6DOF_GY_KALMAN
754  if (six_axis_kalman) scratch16 = (int16_t) (sfg->SV_6DOF_GY_KALMAN.fqgErrPl[i] * 30000.0F);
755 #endif
756 #if F_9DOF_GBY_KALMAN
757  if (nine_axis_kalman) scratch16 = (int16_t) (sfg->SV_9DOF_GBY_KALMAN.fqgErrPl[i] * 30000.0F);
758 #endif
759  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16,2);
760  }
761 
762  // [16-15]: fzmErr[CHX] resolution scaled by 30000
763  // [18-17]: fzmErr[CHY] resolution scaled by 30000
764  // [20-19]: fzmErr[CHZ] resolution scaled by 30000
765  for (i = CHX; i <= CHZ; i++)
766  {
767 #if F_6DOF_GY_KALMAN
768  if (six_axis_kalman) scratch16 = 0;
769 #endif
770 #if F_9DOF_GBY_KALMAN
771  if (nine_axis_kalman) scratch16 = (int16_t) (sfg->SV_9DOF_GBY_KALMAN.fZErr[i + 3] * 30000.0F);
772 #endif
773  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
774  }
775 
776  // [22-21]: fmErrPl[CHX] resolution scaled by 30000
777  // [24-23]: fmErrPl[CHY] resolution scaled by 30000
778  // [26-25]: fmErrPl[CHZ] resolution scaled by 30000
779  for (i = CHX; i <= CHZ; i++)
780  {
781 #if F_6DOF_GY_KALMAN
782  if (six_axis_kalman) scratch16 = 0;
783 #endif
784 #if F_9DOF_GBY_KALMAN
785  if (nine_axis_kalman) scratch16 = (int16_t) (sfg->SV_9DOF_GBY_KALMAN.fqmErrPl[i] * 30000.0F);
786 #endif
787  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
788  }
789 
790  // [28-27]: fbPl[CHX] resolution 0.001 deg/sec
791  // [30-29]: fbPl[CHY] resolution 0.001 deg/sec
792  // [32-31]: fbPl[CHZ] resolution 0.001 deg/sec
793  for (i = CHX; i <= CHZ; i++)
794  {
795 #if F_6DOF_GY_KALMAN
796  if (six_axis_kalman) scratch16 = (int16_t) (sfg->SV_6DOF_GY_KALMAN.fbPl[i] * 1000.0F);
797 #endif
798 #if F_9DOF_GBY_KALMAN
799  if (nine_axis_kalman) scratch16 = (int16_t) (sfg->SV_9DOF_GBY_KALMAN.fbPl[i] * 1000.0F);
800 #endif
801  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
802  }
803 
804  // [34-33]: fDeltaPl resolution 0.01deg
805  scratch16 = 0;
806 #if F_9DOF_GBY_KALMAN
807  if (nine_axis_kalman) scratch16 = (int16_t) (sfg->SV_9DOF_GBY_KALMAN.fDeltaPl * 100.0F);
808 #endif
809  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
810 
811  // [36-35]: fAccGl[CHX] resolution 1/8192 g
812  // [38-37]: fAccGl[CHY] resolution 1/8192 g
813  // [40-39]: fAccGl[CHZ] resolution 1/8192 g
814  for (i = CHX; i <= CHZ; i++)
815  {
816  // default to zero data
817  ftmp = 0.0F;
818 #if F_6DOF_GY_KALMAN
819  if (six_axis_kalman) ftmp = sfg->SV_6DOF_GY_KALMAN.fAccGl[i] * 8192.0F;
820 #endif
821 #if F_9DOF_GBY_KALMAN
822  if (nine_axis_kalman) ftmp = sfg->SV_9DOF_GBY_KALMAN.fAccGl[i] * 8192.0F;
823 #endif
824 
825  // check for clipping
826  if (ftmp > 32767.0F) scratch16 = 32767;
827  else if (ftmp < -32768.0F) scratch16 = -32768;
828  else scratch16 = (int16_t) ftmp;
829  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
830  }
831 
832  // [42-41]: fDisGl[CHX] resolution 0.01m
833  // [44-43]: fDisGl[CHY] resolution 0.01m
834  // [46-45]: fDisGl[CHZ] resolution 0.01m
835  for (i = CHX; i <= CHZ; i++)
836  {
837  // default to zero data
838  ftmp = 0.0F;
839 #if F_9DOF_GBY_KALMAN
840  if (nine_axis_kalman) ftmp = sfg->SV_9DOF_GBY_KALMAN.fDisGl[i] * 100.0F;
841 #endif
842 
843  // check for clipping
844  if (ftmp > 32767.0F) scratch16 = 32767;
845  else if (ftmp < -32768.0F) scratch16 = -32768;
846  else scratch16 = (int16_t) ftmp;
847  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
848  }
849 
850  // [47]: add the tail byte for the Kalman packet type 7
851  sUARTOutputBuffer[iIndex++] = 0x7E;
852  }
853  } // end of check for Kalman packet
854 #endif
855 #if F_USING_ACCEL
856  // *************************************************************************
857  // fixed length packet type 8 transmitted whenever a precision accelerometer
858  // measurement has been stored.
859  // total size is 0 to 40 equals 41 bytes
860  // *************************************************************************
861  // check to see which packet (if any) is to be transmitted
862  if (AccelCalPacketOn != -1)
863  {
864  // [0]: packet start byte (need a iIndex++ here since not using sBufAppendItem)
865  sUARTOutputBuffer[iIndex++] = 0x7E;
866 
867  // [1]: packet type 8 byte (iIndex is automatically updated in sBufAppendItem)
868  tmpuint8_t = 0x08;
869  sBufAppendItem(sUARTOutputBuffer, &iIndex, &tmpuint8_t, 1);
870 
871  // [2]: packet number byte
872  sBufAppendItem(sUARTOutputBuffer, &iIndex, &iPacketNumber, 1);
873  iPacketNumber++;
874 
875  // [3]: AccelCalPacketOn in range 0-11 denotes stored location and MAXORIENTATIONS denotes transmit
876  // precision accelerometer calibration on power on before any measurements have been obtained.
878  (uint8_t *) &(AccelCalPacketOn), 1);
879 
880  // [9-4]: stored accelerometer measurement fGs (scaled to 8192 counts per g)
881  if ((AccelCalPacketOn >= 0) &&
882  (AccelCalPacketOn < MAX_ACCEL_CAL_ORIENTATIONS))
883  {
884  scratch16 = (int16_t) (sfg->AccelBuffer.fGsStored[AccelCalPacketOn][CHX] * 8192.0F);
885  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
886  scratch16 = (int16_t) (sfg->AccelBuffer.fGsStored[AccelCalPacketOn][CHY] * 8192.0F);
887  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
888  scratch16 = (int16_t) (sfg->AccelBuffer.fGsStored[AccelCalPacketOn][CHZ] * 8192.0F);
889  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
890  }
891  else
892  {
893  // transmit zero bytes since this is the power on or reset transmission of the precision calibration
894  sBufAppendZeros(sUARTOutputBuffer, &iIndex, 3);
895  }
896 
897  // [15-10]: precision accelerometer offset vector fV (g scaled by 32768.0)
898  scratch16 = (int16_t) (sfg->AccelCal.fV[CHX] * 32768.0F);
899  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
900  scratch16 = (int16_t) (sfg->AccelCal.fV[CHY] * 32768.0F);
901  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
902  scratch16 = (int16_t) (sfg->AccelCal.fV[CHZ] * 32768.0F);
903  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
904 
905  // [21-16]: precision accelerometer inverse gain matrix diagonal finvW - 1.0 (scaled by 10000.0)
906  scratch16 = (int16_t) ((sfg->AccelCal.finvW[CHX][CHX] - 1.0F) * 10000.0F);
907  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
908  scratch16 = (int16_t) ((sfg->AccelCal.finvW[CHY][CHY] - 1.0F) * 10000.0F);
909  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
910  scratch16 = (int16_t) ((sfg->AccelCal.finvW[CHZ][CHZ] - 1.0F) * 10000.0F);
911  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
912 
913  // [27-22]: precision accelerometer inverse gain matrix off-diagonal finvW (scaled by 10000)
914  scratch16 = (int16_t) (sfg->AccelCal.finvW[CHX][CHY] * 10000.0F);
915  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
916  scratch16 = (int16_t) (sfg->AccelCal.finvW[CHX][CHZ] * 10000.0F);
917  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
918  scratch16 = (int16_t) (sfg->AccelCal.finvW[CHY][CHZ] * 10000.0F);
919  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
920 
921  // [33-28]: precision accelerometer rotation matrix diagonal fR0 (scaled by 10000)
922  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHX][CHX] * 10000.0F);
923  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
924  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHY][CHY] * 10000.0F);
925  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
926  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHZ][CHZ] * 10000.0F);
927  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
928 
929  // [45-34]: precision accelerometer inverse rotation matrix off-diagonal fR0 (scaled by 10000)
930  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHX][CHY] * 10000.0F);
931  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
932  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHX][CHZ] * 10000.0F);
933  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
934  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHY][CHX] * 10000.0F);
935  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
936  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHY][CHZ] * 10000.0F);
937  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
938  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHZ][CHX] * 10000.0F);
939  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
940  scratch16 = (int16_t) (sfg->AccelCal.fR0[CHZ][CHY] * 10000.0F);
941  sBufAppendItem(sUARTOutputBuffer, &iIndex, (uint8_t *) &scratch16, 2);
942 
943  // [46]: add the tail byte for the packet type 8
944  sUARTOutputBuffer[iIndex++] = 0x7E;
945 
946  // disable future packets of this type until a new measurement has been obtained
948  }
949 #endif // F_USING_ACCEL
950  // ********************************************************************************
951  // all packets have now been constructed in the output buffer so now transmit.
952  // The final iIndex++ gives the number of bytes to transmit which is one more than
953  // the last index in the buffer. this function is non-blocking
954  // ********************************************************************************
956  return;
957 }
enum quaternion quaternion_type
the quaternion type to be transmitted
Quaternion derived from full 9-axis sensor fusion.
Definition: sensor_fusion.h:70
#define MAGBUFFSIZEX
x dimension in magnetometer buffer (12x24 equals 288 elements)
Definition: magnetic.h:44
#define F_USING_GYRO
nominally 0x0004 if a gyro is to be used, 0x0000 otherwise
#define CHY
Used to access Y-channel entries in various data data structures.
Definition: sensor_fusion.h:77
void readCommon(SV_ptr data, Quaternion *fq, int16_t *iPhi, int16_t *iThe, int16_t *iRho, int16_t iOmega[], uint16_t *isystick)
uint32_t iFlags
a bit-field of sensors and algorithms used
float q0
scalar component
Definition: orientation.h:39
volatile uint8_t AltPacketOn
flag to enable altitude packet
Definition: control.h:70
Quaternion derived from 3-axis mag only (auto compass algorithm)
Definition: sensor_fusion.h:66
MagCalibration MagCal
mag cal storage
volatile int8_t AccelCalPacketOn
variable used to coordinate accelerometer calibration
Definition: control.h:71
float q3
z vector component
Definition: orientation.h:42
int16_t iMagBufferCount
number of magnetometer readings
Definition: magnetic.h:68
Quaternion derived from 3-axis gyro only (rotation)
Definition: sensor_fusion.h:67
int16_t iCountsPeruT
counts per uT
Quaternion derived from 3-axis accel + 3 axis mag (eCompass)
Definition: sensor_fusion.h:68
Quaternion derived from 3-axis accel + 3-axis gyro (gaming)
Definition: sensor_fusion.h:69
uint16_t throttle()
(OVERSAMPLE_RATIO * MAXPACKETRATEHZ) / SENSORFS
struct ControlSubsystem * pControlSubsystem
MagSensor Mag
magnetometer storage
quaternion structure definition
Definition: orientation.h:37
#define F_1DOF_P_BASIC
1DOF pressure (altitude) and temperature algorithm selector - 0x0100 to include, 0x0000 otherwise ...
#define F_9DOF_GBY_KALMAN
void sBufAppendItem(uint8_t *pDest, uint16_t *pIndex, uint8_t *pSource, uint16_t iBytesToCopy)
Utility function used to place data in output buffer about to be transmitted via UART.
Definition: output_stream.c:59
float finvW[3][3]
current inverse soft iron matrix
Definition: magnetic.h:76
#define THISBUILD
define build number sent in debug packet for display purposes only
float fV[3]
current hard iron offset x, y, z, (uT)
Definition: magnetic.h:75
#define F_6DOF_GY_KALMAN
6DOF accel and gyro (Kalman) algorithm selector - 0x2000 to include, 0x0000 otherwise ...
#define F_3DOF_G_BASIC
3DOF accel tilt (accel) algorithm selector - 0x0200 to include, 0x0000 otherwise
#define CHZ
uint8_t sUARTOutputBuffer[256]
main output buffer defined in control.c
Definition: control.c:59
volatile uint8_t DebugPacketOn
flag to enable debug packet
Definition: control.h:68
#define MAX_ACCEL_CAL_ORIENTATIONS
number of stored precision accelerometer measurements
int16_t iBc[3]
averaged calibrated measurement (counts)
#define CHX
Used to access X-channel entries in various data data structures.
Definition: sensor_fusion.h:76
float fFitErrorpc
current fit error %
Definition: magnetic.h:79
MagBuffer MagBuffer
mag cal constellation points
writePort_t * write
low level function to write a char buffer to the serial stream
Definition: control.h:72
volatile uint8_t RPCPacketOn
flag to enable roll, pitch, compass packet
Definition: control.h:69
Quaternion derived from 3-axis accel (tilt)
Definition: sensor_fusion.h:65
#define F_3DOF_Y_BASIC
3DOF gyro integration algorithm selector - 0x0800 to include, 0x0000 otherwise
#define F_6DOF_GB_BASIC
6DOF accel and mag eCompass algorithm selector - 0x1000 to include, 0x0000 otherwise ...
#define FUSION_HZ
(int) actual rate of fusion algorithm execution and sensor FIFO reads
int32_t index[MAGBUFFSIZEX][MAGBUFFSIZEY]
array of time indices
Definition: magnetic.h:66
void sBufAppendZeros(uint8_t *pDest, uint16_t *pIndex, uint16_t numZeros)
Definition: output_stream.c:92
float fB
current geomagnetic field magnitude (uT)
Definition: magnetic.h:77
#define F_USING_ACCEL
nominally 0x0001 if an accelerometer is to be used, 0x0000 otherwise
#define MAGBUFFSIZEY
y dimension in magnetometer buffer (12x24 equals 288 elements)
Definition: magnetic.h:45
float q2
y vector component
Definition: orientation.h:41
#define F_3DOF_B_BASIC
3DOF mag eCompass (vehicle/mag) algorithm selector - 0x0400 to include, 0x0000 otherwise ...
Excluding SV_1DOF_P_BASIC, Any of the SV_ fusion structures above could be cast to type SV_COMMON for...
#define F_USING_MAG
Definition: magnetic.h:38
float q1
x vector component
Definition: orientation.h:40
int16_t iBs[3][MAGBUFFSIZEX][MAGBUFFSIZEY]
uncalibrated magnetometer readings
Definition: magnetic.h:65
volatile quaternion_type QuaternionPacketType
quaternion type transmitted over UART
Definition: control.h:66
volatile uint8_t AngularVelocityPacketOn
flag to enable angular velocity packet
Definition: control.h:67

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void DecodeCommandBytes ( SensorFusionGlobals sfg,
char  iCommandBuffer[],
uint8  sUART_InputBuffer[],
uint16  nbytes 
)

This function is responsible for decoding commands sent by the NXP Sensor Fusion Toolbox and setting the appropriate flags in the ControlSubsystem data structure. Packet protocols are defined in the NXP Sensor Fusion for Kinetis Product Development Kit User Guide.

Definition at line 90 of file DecodeCommandBytes.c.

Referenced by WIRED_UART_IRQHandler(), and WIRELESS_UART_IRQHandler().

91 {
92  int32 isum; // 32 bit command identifier
93  int16 i, j; // loop counters
94 
95  // parse all received bytes in sUARTInputBuf into the iCommandBuffer delay line
96  for (i = 0; i < nbytes; i++) {
97  // shuffle the iCommandBuffer delay line and add the new command byte
98  for (j = 0; j < 3; j++)
99  iCommandBuffer[j] = iCommandBuffer[j + 1];
100  iCommandBuffer[3] = sUART_InputBuffer[i];
101 
102  // check if we have a valid command yet
103  isum = ((((((int32)iCommandBuffer[0] << 8) | iCommandBuffer[1]) << 8) | iCommandBuffer[2]) << 8) | iCommandBuffer[3];
104  switch (isum) {
105  case cmd_VGplus: // "VG+ " = enable angular velocity packet transmission
107  iCommandBuffer[3] = '~';
108  break;
109 
110  case cmd_VGminus: // "VG- " = disable angular velocity packet transmission
112  iCommandBuffer[3] = '~';
113  break;
114 
115  case cmd_DBplus: // "DB+ " = enable debug packet transmission
116  sfg->pControlSubsystem->DebugPacketOn = true;
117  iCommandBuffer[3] = '~';
118  break;
119 
120  case cmd_DBminus: // "DB- " = disable debug packet transmission
121  sfg->pControlSubsystem->DebugPacketOn = false;
122  iCommandBuffer[3] = '~';
123  break;
124 
125  case cmd_Q3: // "Q3 " = transmit 3-axis accelerometer quaternion in standard packet
126 #if F_3DOF_G_BASIC
128 #endif
129  iCommandBuffer[3] = '~';
130  break;
131 
132  case cmd_Q3M: // "Q3M " = transmit 3-axis magnetometer quaternion in standard packet
133 #if F_3DOF_B_BASIC
135 #endif
136  iCommandBuffer[3] = '~';
137  break;
138 
139  case cmd_Q3G: // "Q3G " = transmit 3-axis gyro quaternion in standard packet
140 #if F_3DOF_Y_BASIC
142 #endif
143  iCommandBuffer[3] = '~';
144  break;
145 
146  case cmd_Q6MA: // "Q6MA" = transmit 6-axis mag/accel quaternion in standard packet
147 #if F_6DOF_GB_BASIC
149 #endif
150  iCommandBuffer[3] = '~';
151  break;
152 
153  case cmd_Q6AG: // "Q6AG" = transmit 6-axis accel/gyro quaternion in standard packet
154 #if F_6DOF_GY_KALMAN
156 #endif
157  iCommandBuffer[3] = '~';
158  break;
159 
160  case cmd_Q9: // "Q9 " = transmit 9-axis quaternion in standard packet (default)
161 #if F_9DOF_GBY_KALMAN
163 #endif
164  iCommandBuffer[3] = '~';
165  break;
166 
167  case cmd_RPCplus: // "RPC+" = Roll/Pitch/Compass on
168  sfg->pControlSubsystem->RPCPacketOn = true;
169  iCommandBuffer[3] = '~';
170  break;
171 
172  case cmd_RPCminus: // "RPC-" = Roll/Pitch/Compass off
173  sfg->pControlSubsystem->RPCPacketOn = false;
174  iCommandBuffer[3] = '~';
175  break;
176 
177  case cmd_ALTplus: // "ALT+" = Altitude packet on
178  sfg->pControlSubsystem->AltPacketOn = true;
179  iCommandBuffer[3] = '~';
180  break;
181 
182  case cmd_ALTminus: // "ALT-" = Altitude packet off
183  sfg->pControlSubsystem->AltPacketOn = false;
184  iCommandBuffer[3] = '~';
185  break;
186 
187  case cmd_RST: // "RST " = Soft reset
188  // reset sensor fusion
189  fInitializeFusion(sfg);
190 
191  // reset magnetic calibration and magnetometer data buffer
192 #if F_USING_MAG
194 #endif
195  // reset precision accelerometer calibration and accelerometer measurements
196 #if F_USING_ACCEL
197  fInitializeAccelCalibration(&sfg->AccelCal, &sfg->AccelBuffer, &(sfg->pControlSubsystem->AccelCalPacketOn)) ;
198 #endif
199  iCommandBuffer[3] = '~';
200  break;
201 
202  case cmd_RINS: // "RINS" = Reset INS inertial navigation velocity and position
203 #if F_9DOF_GBY_KALMAN
204  for (i = CHX; i <= CHZ; i++) {
205  sfg->SV_9DOF_GBY_KALMAN.fVelGl[i] = 0.0F;
206  sfg->SV_9DOF_GBY_KALMAN.fDisGl[i] = 0.0F;
207  }
208 #endif
209  iCommandBuffer[3] = '~';
210  break;
211 
212  case cmd_SVAC: // "SVAC" = save all calibrations to Kinetis flash
216  iCommandBuffer[3] = '~';
217  break;
218 
219  case cmd_SVMC: // "SVMC" = save magnetic calibration to Kinetis flash
221  iCommandBuffer[3] = '~';
222  break;
223 
224  case cmd_SVYC: // "SVYC" = save gyroscope calibration to Kinetis flash
226  iCommandBuffer[3] = '~';
227  break;
228 
229  case cmd_SVGC: // "SVGC" = save precision accelerometer calibration to Kinetis flash
231  iCommandBuffer[3] = '~';
232  break;
233 
234  case cmd_ERAC: // "ERAC" = erase all calibrations from Kinetis flash
238  iCommandBuffer[3] = '~';
239  break;
240 
241  case cmd_ERMC: // "ERMC" = erase magnetic calibration offset 0 bytes from Kinetis flash
243  iCommandBuffer[3] = '~';
244  break;
245 
246  case cmd_ERYC: // "ERYC" = erase gyro offset calibrationoffset 128 bytes from Kinetis flash
248  iCommandBuffer[3] = '~';
249  break;
250 
251  case cmd_ERGC: // "ERGC" = erase precision accelerometer calibration offset 192 bytesfrom Kinetis flash
253  iCommandBuffer[3] = '~';
254  break;
255 
256  case cmd_180X: // "180X" perturbation
257  sfg->iPerturbation = 1;
258  iCommandBuffer[3] = '~';
259  break;
260 
261  case cmd_180Y: // "180Y" perturbation
262  sfg->iPerturbation = 2;
263  iCommandBuffer[3] = '~';
264  break;
265 
266  case cmd_180Z: // "180Z" perturbation
267  sfg->iPerturbation = 3;
268  iCommandBuffer[3] = '~';
269  break;
270 
271  case cmd_M90X: // "M90X" perturbation
272  sfg->iPerturbation = 4;
273  iCommandBuffer[3] = '~';
274  break;
275 
276  case cmd_P90X: // "P90X" perturbation
277  sfg->iPerturbation = 5;
278  iCommandBuffer[3] = '~';
279  break;
280 
281  case cmd_M90Y: // "M90Y" perturbation
282  sfg->iPerturbation = 6;
283  iCommandBuffer[3] = '~';
284  break;
285 
286  case cmd_P90Y: // "P90Y" perturbation
287  sfg->iPerturbation = 7;
288  iCommandBuffer[3] = '~';
289  break;
290 
291  case cmd_M90Z: // "M90Z" perturbation
292  sfg->iPerturbation = 8;
293  iCommandBuffer[3] = '~';
294  break;
295 
296  case cmd_P90Z: // "P90Z" perturbation
297  sfg->iPerturbation = 9;
298  iCommandBuffer[3] = '~';
299  break;
300 
301 #if F_USING_ACCEL
302  case cmd_PA00: // "PA00" average precision accelerometer location 0
303  sfg->AccelBuffer.iStoreLocation = 0;
304  sfg->AccelBuffer.iStoreCounter = (ACCEL_CAL_AVERAGING_SECS * FUSION_HZ);
305  iCommandBuffer[3] = '~';
306  break;
307 
308  case cmd_PA01: // "PA01" average precision accelerometer location 1
309  sfg->AccelBuffer.iStoreLocation = 1;
310  sfg->AccelBuffer.iStoreCounter = (ACCEL_CAL_AVERAGING_SECS * FUSION_HZ);
311  iCommandBuffer[3] = '~';
312  break;
313 
314  case cmd_PA02: // "PA02" average precision accelerometer location 2
315  sfg->AccelBuffer.iStoreLocation = 2;
316  sfg->AccelBuffer.iStoreCounter = (ACCEL_CAL_AVERAGING_SECS * FUSION_HZ);
317  iCommandBuffer[3] = '~';
318  break;
319 
320  case cmd_PA03: // "PA03" average precision accelerometer location 3
321  sfg->AccelBuffer.iStoreLocation = 3;
322  sfg->AccelBuffer.iStoreCounter = (ACCEL_CAL_AVERAGING_SECS * FUSION_HZ);
323  iCommandBuffer[3] = '~';
324  break;
325 
326  case cmd_PA04: // "PA04" average precision accelerometer location 4
327  sfg->AccelBuffer.iStoreLocation = 4;
328  sfg->AccelBuffer.iStoreCounter = (ACCEL_CAL_AVERAGING_SECS * FUSION_HZ);
329  iCommandBuffer[3] = '~';
330  break;
331 
332  case cmd_PA05: // "PA05" average precision accelerometer location 5
333  sfg->AccelBuffer.iStoreLocation = 5;
334  sfg->AccelBuffer.iStoreCounter = (ACCEL_CAL_AVERAGING_SECS * FUSION_HZ);
335  iCommandBuffer[3] = '~';
336  break;
337 
338  case cmd_PA06: // "PA06" average precision accelerometer location 6
339  sfg->AccelBuffer.iStoreLocation = 6;
340  sfg->AccelBuffer.iStoreCounter = (ACCEL_CAL_AVERAGING_SECS * FUSION_HZ);
341  iCommandBuffer[3] = '~';
342  break;
343 
344  case cmd_PA07: // "PA07" average precision accelerometer location 7
345  sfg->AccelBuffer.iStoreLocation = 7;
346  sfg->AccelBuffer.iStoreCounter = (ACCEL_CAL_AVERAGING_SECS * FUSION_HZ);
347  iCommandBuffer[3] = '~';
348  break;
349 
350  case cmd_PA08: // "PA08" average precision accelerometer location 8
351  sfg->AccelBuffer.iStoreLocation = 8;
352  sfg->AccelBuffer.iStoreCounter = (ACCEL_CAL_AVERAGING_SECS * FUSION_HZ);
353  iCommandBuffer[3] = '~';
354  break;
355 
356  case cmd_PA09: // "PA09" average precision accelerometer location 9
357  sfg->AccelBuffer.iStoreLocation = 9;
358  sfg->AccelBuffer.iStoreCounter = (ACCEL_CAL_AVERAGING_SECS * FUSION_HZ);
359  iCommandBuffer[3] = '~';
360  break;
361 
362  case cmd_PA10: // "PA10" average precision accelerometer location 10
363  sfg->AccelBuffer.iStoreLocation = 10;
364  sfg->AccelBuffer.iStoreCounter = (ACCEL_CAL_AVERAGING_SECS * FUSION_HZ);
365  iCommandBuffer[3] = '~';
366  break;
367 
368  case cmd_PA11: // "PA11" average precision accelerometer location 11
369  sfg->AccelBuffer.iStoreLocation = 11;
370  sfg->AccelBuffer.iStoreCounter = (ACCEL_CAL_AVERAGING_SECS * FUSION_HZ);
371  iCommandBuffer[3] = '~';
372  break;
373 #endif // precision accelerometer calibration
374 
375  default:
376  // no action
377  break;
378  }
379  } // end of loop over received characters
380 
381  return;
382 }
#define cmd_PA04
Quaternion derived from full 9-axis sensor fusion.
Definition: sensor_fusion.h:70
void EraseGyroCalibrationFromNVM(void)
void fInitializeFusion(SensorFusionGlobals *sfg)
Definition: fusion.c:51
#define cmd_SVGC
void SaveMagCalibrationToNVM(SensorFusionGlobals *sfg)
#define cmd_SVYC
void fInitializeMagCalibration(MagCalibration *pthisMagCal, MagBuffer *pthisMagBuffer)
Definition: magnetic.c:41
#define cmd_M90Y
#define cmd_PA08
void SaveAccelCalibrationToNVM(SensorFusionGlobals *sfg)
void EraseMagCalibrationFromNVM(void)
volatile uint8_t AltPacketOn
flag to enable altitude packet
Definition: control.h:70
#define cmd_P90Y
Quaternion derived from 3-axis mag only (auto compass algorithm)
Definition: sensor_fusion.h:66
#define cmd_RST
MagCalibration MagCal
mag cal storage
#define cmd_ERGC
#define cmd_VGminus
volatile int8_t AccelCalPacketOn
variable used to coordinate accelerometer calibration
Definition: control.h:71
#define cmd_SVAC
#define cmd_PA10
Quaternion derived from 3-axis gyro only (rotation)
Definition: sensor_fusion.h:67
Quaternion derived from 3-axis accel + 3 axis mag (eCompass)
Definition: sensor_fusion.h:68
int32_t int32
Definition: sensor_fusion.h:57
Quaternion derived from 3-axis accel + 3-axis gyro (gaming)
Definition: sensor_fusion.h:69
#define cmd_DBminus
struct ControlSubsystem * pControlSubsystem
void SaveGyroCalibrationToNVM(SensorFusionGlobals *sfg)
#define cmd_PA05
#define cmd_PA01
#define cmd_P90X
#define cmd_PA00
#define CHZ
#define cmd_DBplus
#define cmd_PA06
#define cmd_PA03
volatile uint8_t DebugPacketOn
flag to enable debug packet
Definition: control.h:68
#define cmd_RPCminus
#define cmd_PA07
#define CHX
Used to access X-channel entries in various data data structures.
Definition: sensor_fusion.h:76
#define cmd_Q3M
#define cmd_P90Z
MagBuffer MagBuffer
mag cal constellation points
#define cmd_SVMC
#define cmd_180Y
#define cmd_ALTplus
#define cmd_PA11
#define cmd_Q3
#define cmd_ALTminus
volatile uint8_t RPCPacketOn
flag to enable roll, pitch, compass packet
Definition: control.h:69
Quaternion derived from 3-axis accel (tilt)
Definition: sensor_fusion.h:65
void EraseAccelCalibrationFromNVM(void)
#define FUSION_HZ
(int) actual rate of fusion algorithm execution and sensor FIFO reads
#define cmd_Q6AG
#define cmd_Q6MA
#define cmd_RPCplus
#define cmd_RINS
#define cmd_ERMC
#define cmd_VGplus
void fInitializeAccelCalibration(struct AccelCalibration *pthisAccelCal, struct AccelBuffer *pthisAccelBuffer, volatile int8 *AccelCalPacketOn)
Initialize the accelerometer calibration functions.
#define cmd_PA02
int16_t int16
Definition: sensor_fusion.h:56
#define cmd_PA09
#define cmd_180X
#define cmd_ERAC
#define ACCEL_CAL_AVERAGING_SECS
calibration constants
#define cmd_180Z
#define cmd_M90X
volatile uint8_t iPerturbation
test perturbation to be applied
volatile quaternion_type QuaternionPacketType
quaternion type transmitted over UART
Definition: control.h:66
#define cmd_M90Z
#define cmd_Q3G
#define cmd_Q9
volatile uint8_t AngularVelocityPacketOn
flag to enable angular velocity packet
Definition: control.h:67
#define cmd_ERYC

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int8_t initializeControlPort ( ControlSubsystem pComm)

Call this once to initialize structures, ports, etc.

Call this once to initialize structures, ports, etc.

Parameters
pCommpointer to the control subystem structure

Definition at line 182 of file control.c.

Referenced by main().

185 {
186  uart_config_t config;
187  if (pComm)
188  {
189  pComm->DefaultQuaternionPacketType = Q3; // default to simplest algorithm
190  pComm->QuaternionPacketType = Q3; // default to simplest algorithm
191  pComm->AngularVelocityPacketOn = true; // transmit angular velocity packet
192  pComm->DebugPacketOn = true; // transmit debug packet
193  pComm->RPCPacketOn = true; // transmit roll, pitch, compass packet
194  pComm->AltPacketOn = true; // Altitude packet
195  pComm->AccelCalPacketOn = 0;
196  pComm->write = writeControlPort;
197  pComm->stream = CreateAndSendPackets;
198 
199 #if F_USE_WIRED_UART
200  /* Initialize WIRED UART pins below - currently duplicates code in pin_mux.c */
201  CLOCK_EnableClock(WIRED_UART_PORT_CLKEN);
202  PORT_SetPinMux(WIRED_UART_PORT, WIRED_UART_RX_PIN, WIRED_UART_MUX);
203  PORT_SetPinMux(WIRED_UART_PORT, WIRED_UART_TX_PIN, WIRED_UART_MUX);
204  UART_GetDefaultConfig(&config);
205 
206  config.baudRate_Bps = CONTROL_BAUDRATE;
207  config.enableTx = true;
208  config.enableRx = true;
209  config.rxFifoWatermark = 1;
210  UART_Init(WIRED_UART, &config, CLOCK_GetFreq(WIRED_UART_CLKSRC));
211 
212  /* Enable RX interrupt. */
213  UART_EnableInterrupts(WIRED_UART, kUART_RxDataRegFullInterruptEnable |
214  kUART_RxOverrunInterruptEnable);
215  EnableIRQ(WIRED_UART_IRQn);
216 #endif
217 #if F_USE_WIRELESS_UART
218  /* Initialize WIRELESS UART pins below */
219  CLOCK_EnableClock(WIRELESS_UART_PORT_CLKEN);
220  PORT_SetPinMux(WIRELESS_UART_PORT, WIRELESS_UART_RX_PIN,
221  WIRELESS_UART_MUX);
222  PORT_SetPinMux(WIRELESS_UART_PORT, WIRELESS_UART_TX_PIN,
223  WIRELESS_UART_MUX);
224 
225  UART_Init(WIRELESS_UART, &config, CLOCK_GetFreq(WIRELESS_UART_CLKSRC));
226  BlueRadios_Init();
227 
228  /* Enable RX interrupt. */
229  UART_EnableInterrupts(WIRELESS_UART, kUART_RxDataRegFullInterruptEnable |
230  kUART_RxOverrunInterruptEnable);
231  EnableIRQ(WIRELESS_UART_IRQn);
232 #endif
233 
234  return (0);
235  }
236  else
237  {
238  return (1);
239  }
240 }
volatile uint8_t AltPacketOn
flag to enable altitude packet
Definition: control.h:70
streamData_t * stream
function to create packets for serial stream
Definition: control.h:73
volatile int8_t AccelCalPacketOn
variable used to coordinate accelerometer calibration
Definition: control.h:71
quaternion_type DefaultQuaternionPacketType
default quaternion transmitted at power on
Definition: control.h:65
int8_t writeControlPort(ControlSubsystem *pComm, uint8_t buffer[], uint16_t nbytes)
Definition: control.c:79
void CreateAndSendPackets(SensorFusionGlobals *sfg, uint8_t *sUARTOutputBuffer)
Called once per fusion cycle to stream information required by the NXP Sensor Fusion Toolbox...
volatile uint8_t DebugPacketOn
flag to enable debug packet
Definition: control.h:68
writePort_t * write
low level function to write a char buffer to the serial stream
Definition: control.h:72
void BlueRadios_Init(void)
Used to initialize the Blue Radios Bluetooth module found on the FRDM-FXS-MULT2-B sensor shield from ...
Definition: control.c:132
volatile uint8_t RPCPacketOn
flag to enable roll, pitch, compass packet
Definition: control.h:69
Quaternion derived from 3-axis accel (tilt)
Definition: sensor_fusion.h:65
#define CONTROL_BAUDRATE
Baudrate to be used for serial communications.
Definition: control.c:53
volatile quaternion_type QuaternionPacketType
quaternion type transmitted over UART
Definition: control.h:66
volatile uint8_t AngularVelocityPacketOn
flag to enable angular velocity packet
Definition: control.h:67

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void sBufAppendItem ( uint8_t *  pDest,
uint16_t *  pIndex,
uint8_t *  pSource,
uint16_t  iBytesToCopy 
)

Utility function used to place data in output buffer about to be transmitted via UART.

Definition at line 59 of file output_stream.c.

Referenced by CreateAndSendPackets(), and sBufAppendZeros().

61 {
62  uint16_t i; // loop counter
63 
64  // loop over number of bytes to add to the destination buffer
65  for (i = 0; i < iBytesToCopy; i++)
66  {
67  switch (pSource[i])
68  {
69  case 0x7E:
70  // special case 1: replace 0x7E (start and end byte) with 0x7D and 0x5E
71  pDest[(*pIndex)++] = 0x7D;
72  pDest[(*pIndex)++] = 0x5E;
73  break;
74 
75  case 0x7D:
76  // special case 2: replace 0x7D with 0x7D and 0x5D
77  pDest[(*pIndex)++] = 0x7D;
78  pDest[(*pIndex)++] = 0x5D;
79  break;
80 
81  default:
82  // general case, simply add this byte without change
83  pDest[(*pIndex)++] = pSource[i];
84  break;
85  }
86  }
87 
88  return;
89 }

+ Here is the caller graph for this function:

Variable Documentation

uint8_t sUARTOutputBuffer[256]

main output buffer defined in control.c

Definition at line 59 of file control.c.